import numpy as np
import pandas as pd

from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.utils import shuffle
from sklearn.externals import joblib
from sklearn.svm import SVC

from src.code.data_process import Data_Proccess


class Algorithm_Run:
    default_music_csv_file_path = '../../doc/data/csv/music_features.csv'
    default_model_file_path = '../../doc/model/music_model.pkl'
    
    #精确度
    def get_precision(self,res,tes):
        n=len(tes)
        is_equal=(res==tes)
        pre=0
        for flag in is_equal:
            if flag:
                pre+=1
        return (pre*100)/n

    def get_index_label_dict(self):
        data_process=Data_Proccess()
        index_lable_dict=data_process.fetch_index_label()
        return index_lable_dict
    
    def fetch_predict_label(self,clf,X):
        label_index=clf.predict([X])
        index_label_dict=self.get_index_label_dict()
        label=index_label_dict[label_index[0]]
        return label
    
    def internal_cross_validation(self,X,Y):
        parameters={
            'kernel':('linear','rbf','poly'),
            'C':[0.1,1],
            'probability':[True,False],
            'decision_function_shape':['ovo','ovr']
        }
        clf=GridSearchCV(SVC(random_state=0),param_grid=parameters,cv=5)#固定格式
        print('开始交叉验证获取最优参数构建')
        clf.fit(X,Y)
        print('最优参数：',end='')
        print(clf.best_params_)
        print('最优模型准确率：',end='')
        print(clf.best_score_)
    
    def cross_validation(self,music_csv_file_path=None,data_percentage=0.7):
        if not music_csv_file_path:
            music_csv_file_path=self.default_music_csv_file_path
        print('开始读取数据：'+music_csv_file_path)
        data=pd.read_csv(music_csv_file_path,sep=',',header=None,encoding='utf-8')
        sample_fact=0.7
        if isinstance(data_percentage, float) and 0<data_percentage<1:
            sample_fact=data_percentage
        data=data.sample(frac=sample_fact).T
        X=data[:-1].T
        Y=np.array(data[-1:])[0]
        self.internal_cross_validation(X, Y)
    
    #进行模型训练，并且计算训练集上预测值与label的准确性
    def poly(self,X,Y):
        clf=SVC(kernel='poly',C=0.1,probability=True,decision_function_shape='ovo',random_state=0)
        clf.fit(X,Y)
        predict=clf.predict(X)
        precision=self.get_precision(predict, Y)
        return clf,precision
    
    def fit_dump_model(self,train_percentage=0.7,fold=1,music_csv_file_path=None,model_out_f=None):
        if not music_csv_file_path:
            music_csv_file_path=self.default_music_csv_file_path
        data=pd.read_csv(music_csv_file_path,sep=',',header=None,encoding='utf-8')
        
        max_train_source=None
        max_test_source=None
        max_source=None
        best_clf=None
        flag=True
        for index in range(1,int(fold)+1):
            shuffle_data=shuffle(data)
            X=shuffle_data.T[:-1].T
            Y=np.array(shuffle_data.T[-1:])[0]
            x_train,x_test,y_train,y_test=train_test_split(X,Y,train_size=train_percentage)
            (clf,train_source)=self.poly(x_train, y_train)
            y_predict=clf.predict(x_test)
            test_source=self.get_precision(y_predict, y_test)
            source=0.35*train_source+0.65*test_source
            if flag:
                max_source=source
                max_train_source=train_source
                max_test_source=test_source
                best_clf=clf
                flag=False
            else:
                if max_source<source:
                    max_source=source
                    max_train_source=train_source
                    max_test_source=test_source
                    best_clf=clf
            print('第%d次训练，训练集上的正确率为：%0.2f, 测试集上正确率为：%0.2f,加权平均正确率为：%0.2f' %\
                  (index, train_source, test_source, source))
        print('最优模型效果：训练集上的正确率为：%0.2f,测试集上的正确率为：%0.2f, 加权评卷正确率为：%0.2f' %\
              (max_train_source,max_test_source,max_source))
        print('最优模型是：')
        print(best_clf)
        if not model_out_f:
            model_out_f=self.default_model_file_path
        joblib.dump(best_clf,model_out_f)        
    
    def load_model(self,model_f=None):
        if not model_f:
            model_f=self.default_model_file_path
        clf=joblib.load(model_f)
        return clf
        
        
        